home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / xvisrc.zip / IBMPC_A.ASM < prev    next >
Assembly Source File  |  1992-07-28  |  20KB  |  966 lines

  1. ; Copyright (c) 1990,1991,1992 Chris and John Downey
  2. _TEXT    segment word public 'CODE'
  3.     db    "@(#)ibmpc_a.asm    2.1 (Chris & John Downey) 7/29/92"
  4.     db    0
  5. _TEXT    ends
  6.  
  7. ;***
  8. ;
  9. ; program name:
  10. ;    xvi
  11. ; function:
  12. ;    PD version of UNIX "vi" editor, with extensions.
  13. ; module name:
  14. ;    ibmpc_a.asm
  15. ; module function:
  16. ;    Assembly language part of terminal interface module for IBM PC
  17. ;    compatibles running MS-DOS.
  18. ;
  19. ;    This code has been assembled with Microsoft's Macro Assembler
  20. ;    (MASM) version 5.1, & is compatible with code generated by
  21. ;    MS-DOS C compilers using the normal large memory model calling
  22. ;    conventions. This includes the Microsoft & Zortech compilers.
  23. ;
  24. ;    If we're running on a mono system, or one with an EGA or VGA,
  25. ;    & we were started in a text mode, we can achieve much faster
  26. ;    display output by writing directly to the frame buffer; we can
  27. ;    also save the previous screen contents & restore them when we
  28. ;    exit or run a sub-shell, which can be useful. If we have a
  29. ;    CGA, or we were started in a graphics mode, we just use the
  30. ;    functions supplied by the PC BIOS, which are slower, but good
  31. ;    enough for most purposes. On a modern 80386-based system, the
  32. ;    difference in speed is hardly noticeable.
  33. ; history:
  34. ;
  35. ;    STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  36. ;    Originally by Tim Thompson (twitch!tjt)
  37. ;    Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  38. ;    Heavily modified by Chris & John Downey
  39. ;***
  40.  
  41. include 8086mm.inc
  42.  
  43. ;
  44. ; If SWAPSCREEN is defined, we attempt to save the previous screen
  45. ; image & restore it when we exit or run another process. If you don't
  46. ; want this to happen, just comment out the line below.
  47. ;
  48. SWAPSCREEN    equ    1
  49.  
  50. ;
  51. ; If you don't want mouse input handling, comment out the line below.
  52. ;
  53. MOUSE        equ    1
  54.  
  55.     C_extern _malloc
  56.     C_extern _cparams
  57.  
  58.     public    _alert
  59.     public    _erase_display
  60.     public    _erase_line
  61.     public    _flush_output
  62.     public    _hidemouse
  63.     public    _mousestatus
  64.     public    _outchar
  65.     public    _outstr
  66.     public    _scroll_up
  67.     public    _scroll_down
  68.     public    _set_colour
  69.     public    _showmouse
  70.     public    _tty_endv
  71.     public    _tty_goto
  72.     public    _tty_open
  73.     public    _tty_startv
  74.  
  75. ;
  76. ; Segment addresses for PC text mode frame buffer.
  77. ;
  78. VMONOSEG    =    0b000h    ; Mono frame buffer.
  79. VCOLOURSEG    =    0b800h    ; Colour frame buffer.
  80.  
  81. ;
  82. ; BIOS video functions.
  83. ;
  84. vbios        macro    ahval, alval
  85.     ifnb    <ahval>
  86.         ifnb <alval>
  87.         mov    ax, (ahval shl 8) + alval
  88.         else
  89.         mov    ah, ahval
  90.         endif
  91.     endif
  92.         int    10h
  93.         endm
  94. ;
  95. ; BIOS video function numbers.
  96. ;
  97. B_MOVECURSOR    =    2    ; Move cursor.
  98. B_UPSCROLL    =    6    ; Scroll window up.
  99. B_DOWNSCROLL    =    7    ; Scroll window down.
  100. B_WRITECHAR    =    9    ; Write character & attribute at
  101.                 ; current position.
  102. B_TTYWRITE    =    0eh    ; Teletype-style write.
  103. B_GETMODE    =    0fh    ; Get video mode.
  104. B_SETPALETTE    =    10h    ; Set palette registers.
  105. B_EGACGEN    =    11h    ; EGA character generator.
  106. B_VCONFIG    =    12h    ; Video subsystem configuration.
  107.  
  108. ;
  109. ; Subfunction (of function 10h) for setting overscan register.
  110. ;
  111. B_OVERSCAN    =    1
  112.  
  113. ;
  114. ; Subfunctions for EGA character generator.
  115. ;
  116. B_EGATEST    =    30h
  117. B_8X8FONT    =    12h
  118. B_8X14FONT    =    11h
  119.  
  120. ;
  121. ; BIOS function to use alternate print screen routine.
  122. ;
  123. altpscreen    macro
  124.         mov    bl, 20h
  125.         vbios    B_VCONFIG
  126.         endm
  127.  
  128. ;
  129. ; BIOS function to get equipment list.
  130. ;
  131. biosequip    macro
  132.         int    11h
  133.         endm
  134. ;
  135. ; Value returned by biosequip (in ax) to indicate a mono display.
  136. ;
  137. EQUIP_MONO    =    30h
  138.  
  139. ;
  140. ; Default number of rows in text modes.
  141. ;
  142. DEF_T_ROWS    =    25
  143.  
  144. ;
  145. ; Video modes.
  146. ;
  147. BWT25X80    =    2    ; 25 x 80 black & white (CGA) text.
  148. CT25X80        =    3    ; 25 x 80 colour text.
  149. MT25X80        =    7    ; 25 x 80 monochrome (MDA) text.
  150.  
  151. ;
  152. ; I/O ports.
  153. ;
  154. TIMER_2        =    42h    ; Timer channel 2.
  155. TIMER_3        =    43h    ; Timer channel 3.
  156. PORT_B        =    61h    ; 8255 port B.
  157.  
  158. ;
  159. ; Interrupt used by Microsoft mouse driver.
  160. ;
  161. MSMINT        =    33h
  162.  
  163. ;
  164. ; Call mouse driver.
  165. ;
  166. msmouse        macro    funcnum
  167.     ifnb    <funcnum>
  168.         mov    ax, funcnum
  169.     endif
  170.         int    MSMINT
  171.         endm
  172. ;
  173. ; Mouse driver function numbers.
  174. ;
  175. MSM_SHOW    =    1
  176. MSM_HIDE    =    2
  177. MSM_GETSTATUS    =    3
  178. MSM_SETYLIMITS    =    8
  179.  
  180. ;
  181. ; Values for mouseflag.
  182. ;
  183. MF_NOMOUSE    =    -1
  184. MF_INITIAL    =    0
  185. MF_OK        =    1
  186. MF_VISIBLE    =    2
  187.  
  188. ;
  189. ; Segment containing interrupt vector table.
  190. ;
  191. INTVECTAB    segment at 0
  192.         ;
  193.         ; Vector used by Microsoft mouse driver.
  194.         ;
  195.         org (MSMINT * 4)
  196. msvecoff    dw    ?
  197. msvecseg    dw    ?
  198. INTVECTAB    ends
  199.  
  200. ;
  201. ; BIOS variable data segment.
  202. ;
  203. BVSEG        =    40h
  204.  
  205. BIOSDATA    segment at BVSEG
  206.         ;
  207.         ; Low word of timer variable.
  208.         ;
  209.         org    6ch
  210. b_timer_low    dw    ?
  211.         ;
  212.         ; Variable giving number of screen rows - 1.
  213.         ;
  214.         org    84h
  215. b_rowsvar    db    ?
  216. BIOSDATA    ends
  217.  
  218. _TEXT        segment word public 'CODE'
  219.         assume    nothing
  220.         assume    cs: _TEXT
  221.  
  222.         even
  223.     ifdef    SWAPSCREEN
  224. saveptr        label    dword    ; Pointer to saved screen image.
  225. svboff        dw    0
  226. svbseg        dw    0
  227. scrwords    dw    ?    ; Number of 2-byte words in saved
  228.                 ; screen image.
  229.     endif    ; SWAPSCREEN
  230. vbase        dw    0    ; Segment address of frame buffer. If
  231.                 ; this is 0, we don't access the frame
  232.                 ; buffer directly.
  233. vcolumn        label    byte
  234. vpos        dw    ?    ; Virtual screen position.
  235. scrsize        label    word    ; Screen dimensions.
  236. ncolumns    db    ?    ; Low byte of scrsize.
  237. nrows        db    ?    ; High byte of scrsize.
  238. writemethod    dw    offset bioswrite
  239.                 ; Pointer to function we use for
  240.                 ; outputting characters to the screen.
  241. startmode    db    ?
  242. ega        db    0    ; Flag indicating presence of EGA/VGA.
  243. vcolour        db    ?    ; Virtual colour.
  244.     ifdef    MOUSE
  245. mouseflag    db    MF_INITIAL
  246.                 ; This is changed by _tty_startv to
  247.                 ; MF_OK if we have a mouse driver
  248.                 ; installed, or MF_NOMOUSE if we
  249.                 ; haven't.
  250.     else    ; MOUSE
  251. mouseflag    db    MF_NOMOUSE
  252.     endif    ; MOUSE
  253.  
  254.     ifdef    SWAPSCREEN
  255.     ;
  256.     ; These routines deal with saving the previous screen image &
  257.     ; restoring it.
  258.     ;
  259. savescreen:
  260.         cmp    vbase, 0
  261.         je    dontcopy
  262.         push    si
  263.         push    di
  264.         push    ds
  265.         les    di, saveptr
  266.         mov    ax, es
  267.         or    ax, di
  268.         jz    cps_pop
  269.         mov    ds, vbase
  270.         clear    si
  271.         jmp short copyscreen
  272.  
  273. restorescreen    proc    near
  274.         cmp    vbase, 0
  275.         je    dontcopy
  276.         push    si
  277.         push    di
  278.         push    ds
  279.         mov    es, vbase
  280.         clear    di
  281.         lds    si, saveptr
  282.         mov    ax, ds
  283.         or    ax, si
  284.         jz    cps_pop
  285. copyscreen:
  286.         mov    cx, scrwords
  287.         cld
  288.         rep    movsw
  289. cps_pop:
  290.         pop    ds
  291.         pop    di
  292.         pop    si
  293. dontcopy:
  294.         ret
  295. restorescreen    endp
  296.     endif    ; SWAPSCREEN
  297.  
  298.         even
  299. _flush_output:
  300.         ;
  301.         ; void flush_output(void);
  302.         ;
  303.         ; Update real cursor position.
  304.         ;
  305.         push    bp
  306.         mov    dx, vpos
  307.         clear    bh        ; Display page 0.
  308.         vbios    B_MOVECURSOR
  309.         pop    bp
  310.         C_ret
  311.  
  312.         even
  313. _erase_line:
  314.         ;
  315.         ; void erase_line(void);
  316.         ;
  317.         ; Erase to end of line.
  318.         ;
  319.         ; Don't update cursor position.
  320.         ;
  321.         mov    cl, ncolumns    ; Get width of screen.
  322.         mov    al, vcolumn    ; Get current column.
  323.         sub    cl, al        ; Number of spaces to write ...
  324.         jz    noerase        ; ... except if it's 0 ...
  325.         clear    ch
  326.         mov    al, ' '
  327.         cld
  328.         call    [writemethod]
  329. noerase:
  330.         C_ret
  331.  
  332. _erase_display:
  333.         ;
  334.         ; void erase_display(void);
  335.         ;
  336.         ; Erase entire display by using BIOS scroll screen
  337.         ; function to scroll all the lines in the display.
  338.         ;
  339.         ; Don't update cursor position.
  340.         ;
  341.         call    _cparams    ; This is in ibmpc_c.c.
  342.         mov    bh, al        ; Get colour for blank screen.
  343.         push    bp
  344.         clear    cx        ; Top left row & column (0).
  345.         mov    al, nrows    ; Number of lines (0).
  346.         mov    dx, scrsize
  347.         dec    dh        ; Bottom right row.
  348.         dec    dl        ; Bottom right column.
  349.         vbios    B_UPSCROLL
  350.         pop    bp
  351.         C_ret
  352.  
  353.         even
  354. _showmouse:
  355.         ;
  356.         ; void showmouse(void);
  357.         ;
  358.         ; Show mouse cursor.
  359.         ;
  360.         ; If we don't seem to have a mouse driver, or we think
  361.         ; the cursor is already visible, don't do anything.
  362.         ;
  363.         cmp    mouseflag, MF_OK
  364.         jne    m_invalid
  365.         mov    ax, MSM_SHOW
  366.         mov    mouseflag, MF_VISIBLE
  367. m_valid:
  368.         msmouse
  369. m_invalid:
  370.         C_ret
  371.  
  372.         even
  373. _hidemouse:
  374.         ;
  375.         ; void hidemouse(void);
  376.         ;
  377.         ; Hide mouse cursor.
  378.         ;
  379.         ; If we don't seem to have a mouse driver, or we don't
  380.         ; think the cursor is visible, don't do anything.
  381.         ;
  382.         cmp    mouseflag, MF_VISIBLE
  383.         jne    m_invalid
  384.         mov    ax, MSM_HIDE
  385.         mov    mouseflag, MF_OK
  386.         jmp short m_valid
  387.  
  388. _mousestatus:
  389.         ;
  390.         ; unsigned mousestatus(unsigned *xpos, unsigned *ypos);
  391.         ;
  392.         ; Return mouse button status, with current mouse
  393.         ; co-ordinates in *xpos & *ypos.
  394.         ;
  395.         push    bp
  396.         mov    bp, sp
  397.         cmp    mouseflag, MF_OK
  398.         jge    getstatus    ; if it's MF_OK or MF_VISIBLE
  399.         clear    ax        ; Button status = 0.
  400.         cwd            ; y co-ordinate = 0.
  401.         mov    cx, ax        ; x co-ordinate = 0.
  402.         jmp short ms_finish
  403. getstatus:
  404.         msmouse MSM_GETSTATUS
  405.         mov    ax, bx        ; Return button status in ax.
  406. ms_finish:
  407.         ;
  408.         ; Stack frame:
  409.         ;
  410.         ;   bp + CPTRSIZE + DPTRSIZE + 2
  411.         ;        ypos pointer
  412.         ;
  413.         ;   bp + CPTRSIZE + 2
  414.         ;        xpos pointer
  415.         ;
  416.         ;   bp + 2    return address
  417.         ;
  418.         ;   bp        caller's bp
  419.         ;
  420.     if DPTRSIZE eq 4
  421.         push    ds
  422.     endif
  423.         ptrasg    <[bp + CPTRSIZE + 2]>, cx
  424.                 ; x co-ordinate.
  425.         assume    ds: nothing
  426.         ptrasg    <[bp + CPTRSIZE + DPTRSIZE + 2]>, dx
  427.                 ; y co-ordinate.
  428.     if DPTRSIZE eq 4
  429.         pop    ds
  430.     endif
  431.         pop    bp
  432.         C_ret
  433.  
  434. _tty_open:
  435.         ;
  436.         ; void tty_open(unsigned int *prows, unsigned int *pcolumns);
  437.         ;
  438.         ; Initialize display. Parameters point to variables in
  439.         ; caller's default data segment giving dimensions of
  440.         ; screen. We also maintain our own record of these
  441.         ; values in scrsize, in this segment.
  442.         ;
  443.         push    bp
  444.         push    ds
  445.         mov    ax, cs
  446.         mov    ds, ax
  447.         assume    ds: _TEXT
  448.         clear    dx
  449.         mov    bx, dx
  450.         vbios    B_EGACGEN, B_EGATEST    ; Do we have an EGA/VGA?
  451.         tst    dl
  452.         jz    notega
  453.         inc    dl        ; Yes: dl is number of rows - 1.
  454.         inc    ega
  455.         jmp short testmode
  456. notega:
  457.         mov    dl, DEF_T_ROWS    ; No: assume 25 rows.
  458. testmode:
  459.         vbios    B_GETMODE
  460.         mov    bp, sp
  461.         mov    cx, cs
  462.         ;
  463.         ; Register usage at this point:
  464.         ;
  465.         ;    al    current display mode
  466.         ;    ah    number of text columns
  467.         ;    cx    our code segment
  468.         ;    dl    number of text rows
  469.         ;    bp    pointer (relative to ss) to stack frame
  470.         ;
  471.         ; Stack frame:
  472.         ;
  473.         ;   bp + CPTRSIZE + DPTRSIZE + 4
  474.         ;        pointer to screen columns variable
  475.         ;
  476.         ;   bp + CPTRSIZE + 4
  477.         ;        pointer to screen rows variable
  478.         ;
  479.         ;   bp + 4    return address
  480.         ;
  481.         ;   bp + 2    caller's bp
  482.         ;
  483.         ;   bp        caller's ds
  484.         ;
  485.         mov    ncolumns, ah
  486.         mov    nrows, dl
  487.     if DPTRSIZE eq 2
  488.         mov    ds, [bp]
  489.         assume    ds: nothing
  490.     endif
  491.         clear    dh        ; Clear high byte of rows.
  492.         ptrasg    <[bp + CPTRSIZE + 4]>, dx
  493.                     ; Return rows to caller.
  494.         assume    ds: nothing
  495.         mov    dl, ah
  496.         ptrasg    <[bp + CPTRSIZE + DPTRSIZE + 4]>, dx
  497.         mov    ds, cx        ; Point ds to our code segment again.
  498.         assume    ds: _TEXT
  499.         mov    startmode, al
  500.         cmp    al, MT25X80    ; Mono text mode?
  501.         jne    notmda
  502.         biosequip
  503.         and    ax, EQUIP_MONO    ; Is it a real mono system?
  504.         cmp    ax, EQUIP_MONO
  505.         jne    notmda        ; No.
  506.         mov    vbase, VMONOSEG
  507.         jmp short directvideo
  508. notmda:
  509.         cmp    al, CT25X80    ; Is it a graphics mode?
  510.         ja    o_finish    ; Yes.
  511.         cmp    ega, 0        ; Do we have an EGA or VGA?
  512.         je    o_finish    ; No.
  513.         mov    vbase, VCOLOURSEG
  514. directvideo:
  515.         mov    writemethod, offset fastwrite
  516.     ifdef    SWAPSCREEN
  517.         mov    ax, scrsize
  518.         dec    ah        ; (number of rows - 1) ...
  519.         mul    ah        ; times (number of columns) ...
  520.         mov    scrwords, ax    ; = number of screen
  521.                     ; characters to save ...
  522.         shl    ax, 1        ; times 2 = number of bytes to save.
  523.         mov    ds, [bp]    ; Restore ds for C library.
  524.         assume    ds: nothing
  525.         push    ax
  526.         call    _malloc
  527.         inc    sp
  528.         inc    sp
  529.     if DPTRSIZE eq 2
  530.         cwd            ; if (ax == 0) dx = 0;
  531.         tst    ax        ; if (malloc() returned NULL) ...
  532.         jz    dxok        ; ... dx should also be 0.
  533.         mov    dx, ds        ; ds now points to C data segment,
  534.                     ; not our code segment.
  535. dxok:
  536.     endif    ; DPTRSIZE eq 2
  537.         mov    svboff, ax
  538.         mov    svbseg, dx
  539.     endif    ; SWAPSCREEN
  540. o_finish:
  541.         pop    ds
  542.         assume    ds: nothing
  543.         pop    bp
  544.         C_ret
  545.  
  546. _tty_startv:
  547.         ;
  548.         ; void tty_startv();
  549.         ;
  550.         ; If we've run a child process, & the mode has
  551.         ; changed, we do our level best to restore it to what
  552.         ; it was before: otherwise we're in trouble because
  553.         ; the screen dimensions have probably changed.
  554.         ;
  555.         push    bp
  556.         push    ds
  557.         mov    ax, cs
  558.         mov    ds, ax
  559.         assume    ds: _TEXT
  560.         vbios    B_GETMODE
  561.         mov    dx, scrsize
  562.         cmp    al, startmode    ; Has mode changed since we started?
  563.         jne    changemode
  564.         cmp    ah, dl        ; Current number of columns is
  565.                     ; in ah; check that it hasn't
  566.                     ; changed.
  567.         je    modeok        ; It hasn't.
  568. changemode:
  569.         mov    al, startmode
  570.         clear    ah        ; Function 0 (set mode).
  571.         vbios
  572.         mov    al, startmode
  573. modeok:
  574.         cmp    ega, 0
  575.         je    sv_save
  576.         ;
  577.         ; If we have an EGA/VGA, the number of rows may have
  578.         ; changed even though the mode hasn't, because
  579.         ; fonts with different sizes can be loaded.
  580.         ;
  581.         cmp    al, BWT25X80
  582.         je    checkrows
  583.         cmp    al, CT25X80
  584.         je    checkrows
  585.         cmp    al, MT25X80
  586.         jne    sv_save
  587. checkrows:                ; Check number of rows.
  588.         mov    ax, BVSEG
  589.         mov    es, ax
  590.         assume    es: BIOSDATA
  591.         mov    al, b_rowsvar
  592.         inc    al
  593.         cmp    al, dh
  594.         jae    sv_save
  595.         altpscreen
  596.         assume    es: nothing
  597.         mov    ax, (B_EGACGEN shl 8) + B_8X14FONT
  598.                     ; Use default EGA font.
  599.         cmp    dh, DEF_T_ROWS
  600.         jbe    setegafont
  601.         mov    ax, (B_EGACGEN shl 8) + B_8X8FONT
  602.                     ; Use small font.
  603. setegafont:
  604.         clear    bl        ; Table 0 in character generator RAM.
  605.         vbios
  606. sv_save:
  607.     ifdef    SWAPSCREEN
  608.         call    savescreen
  609.     endif    ; SWAPSCREEN
  610.     ifdef    MOUSE
  611.         cmp    mouseflag, MF_INITIAL
  612.         js    sv_finish    ; MF_NOMOUSE?
  613.         jne    mousereset    ; MF_OK or MF_VISIBLE?
  614.         clear    ax
  615.         mov    es, ax
  616.         assume    es: INTVECTAB
  617.         mov    ax, msvecoff    ; Check the actual interrupt
  618.         or    ax, msvecseg    ; vector for the mouse driver.
  619.         jz    sv_nomouse    ; If it's 0, we can't call it.
  620. mousereset:
  621.         assume    es: nothing
  622.         clear    ax        ; Function 0 (initialize mouse
  623.         msmouse            ; driver).
  624.         tst    ax
  625.         jz    sv_nomouse        ; Failure.
  626.         mov    mouseflag, MF_OK    ; Success.
  627.         ;
  628.         ; Set vertical limits for mouse movement according to
  629.         ; the number of screen rows; apparently the Microsoft
  630.         ; driver sometimes gets this wrong.
  631.         ;
  632.         mov    dl, nrows    ; Let dx = (nrows - 1) * 8.
  633.         dec    dl
  634.         clear    dh
  635.         mov    cl, 3
  636.         shl    dx, cl
  637.         clear    cx
  638.         msmouse MSM_SETYLIMITS
  639.         jmp short sv_finish
  640. sv_nomouse:
  641.         mov    mouseflag, MF_NOMOUSE
  642.     endif    ; MOUSE
  643. sv_finish:
  644.         pop    ds
  645.         assume    ds: nothing
  646.         pop    bp
  647.         C_ret
  648.  
  649. _tty_endv:
  650.         ;
  651.         ; void tty_endv();
  652.         ;
  653.         ; We're about to exit or run another process. Restore
  654.         ; previous screen if appropriate, update real cursor
  655.         ; position & reset mouse driver to its default state
  656.         ; if required.
  657.         ;
  658.     ifdef    SWAPSCREEN
  659.         ;
  660.         ; At this stage, sys_endv() should have just gone to
  661.         ; the bottom line, set the colour to
  662.         ; Pn(P_systemcolour) & cleared the line. We shouldn't
  663.         ; disturb its work, so restorescreen just restores the
  664.         ; top (nrows - 1) lines. This is controlled by the
  665.         ; scrwords variable.
  666.         ;
  667.         call    restorescreen
  668.     endif    ; SWAPSCREEN
  669.         Cn_call _flush_output
  670.         cmp    mouseflag, MF_INITIAL
  671.         jle    ev_finish
  672.         clear    ax
  673.         msmouse
  674. ev_finish:
  675.         C_ret
  676.  
  677.         even
  678. _tty_goto:
  679.         ;
  680.         ; void tty_goto(int row, int column);
  681.         ;
  682.         ; Change virtual screen position.
  683.         ;
  684.         mov    bx, sp
  685.         mov    ah, byte ptr ss:[bx + CPTRSIZE]
  686.         mov    al, byte ptr ss:[bx + CPTRSIZE + 2]
  687.         mov    vpos, ax
  688.         C_ret
  689.  
  690. _set_colour:
  691.         ;
  692.         ; void set_colour(int colour);
  693.         ;
  694.         ; Change virtual screen colour.
  695.         ;
  696.         mov    bx, sp
  697.         mov    al, byte ptr ss:[bx + CPTRSIZE]
  698.         mov    vcolour, al
  699.         C_ret
  700.  
  701. ;
  702. ; These two routines are functionally equivalent; they are only called
  703. ; by indirection through the "writemethod" pointer.
  704. ;
  705.         even
  706. fastwrite    proc    near
  707.         ;
  708.         ; Write single character, or a number of repetitions
  709.         ; of the same character, to the screen. Character is
  710.         ; in al, number of repetitions in cx.
  711.         ;
  712.         ; This writes directly to the text mode frame buffer.
  713.         ;
  714.         ; Note that:
  715.         ;
  716.         ;    - the direction flag must be clear.
  717.         ;
  718.         ;    - cx is destroyed.
  719.         ;
  720.         push    di
  721.         mov    es, vbase
  722.         mov    dx, vpos    ; Get offset into frame buffer.
  723.         mov    bl, ncolumns
  724.         xchg    ax, bx        ; al is now number of columns;
  725.                     ; bl is character to write ...
  726.         mul    dh        ; ax is now (current row *
  727.                     ;         number of columns) ...
  728.         clear    dh
  729.         add    ax, dx        ; Add current column (dl).
  730.         shl    ax, 1        ; Multiply by 2 to get word offset.
  731.         mov    di, ax
  732.         mov    al, bl        ; Retrieve character to write.
  733.         mov    ah, vcolour
  734.         rep    stosw        ; Do the actual copying.
  735.         pop    di
  736.         ret
  737. fastwrite    endp
  738.  
  739.         even
  740. bioswrite    proc    near
  741.         ;
  742.         ; Write single character, or a number of repetitions
  743.         ; of the same character, to the screen. Character is
  744.         ; in al, number of repetitions in cx.
  745.         ;
  746.         ; This uses the BIOS B_WRITECHAR function.
  747.         ;
  748.         push    bp
  749.         clear    bh        ; Display page 0.
  750.         mov    dx, vpos
  751.         push    ax
  752.         vbios    B_MOVECURSOR
  753.         pop    ax
  754.         mov    bl, vcolour
  755.         vbios    B_WRITECHAR
  756.         pop    bp
  757.         ret
  758. bioswrite    endp
  759.  
  760.         even
  761. vpadjust    proc    near
  762.         ;
  763.         ; Adjust virtual cursor position.
  764.         ;
  765.         mov    ax, scrsize
  766.         mov    dx, vpos
  767.         inc    dl        ; Increment column.
  768.         cmp    dl, al
  769.         jb    adjust
  770.         clear    dl        ; Wrap round to next line.
  771.         inc    dh
  772.         cmp    dh, ah
  773.         jnb    vpa_finish
  774. adjust:
  775.         mov    vpos, dx
  776. vpa_finish:
  777.         ret
  778. vpadjust    endp
  779.  
  780.         even
  781. _outchar:
  782.         ;
  783.         ; void outchar(int character);
  784.         ;
  785.         ; Display one character.
  786.         ;
  787.         mov    bx, sp
  788.         mov    al, byte ptr ss:[bx + CPTRSIZE]
  789.         mov    cx, 1
  790.         cld
  791.         call    [writemethod]
  792.         call    vpadjust
  793.         C_ret
  794.  
  795.         even
  796. _outstr:
  797.         ;
  798.         ; void outstr(char *string);
  799.         ;
  800.         ; Display C string.
  801.         ;
  802.         mov    bx, sp
  803.         push    si
  804.  
  805.     if DPTRSIZE eq 4
  806.         push    ds
  807.         lds    si, ss:[bx + CPTRSIZE]
  808.         assume    ds: nothing
  809.     else
  810.         mov    si, [bx + CPTRSIZE]
  811.     endif
  812.         cld
  813. getnextc:
  814.         lodsb            ; Get next character in al.
  815.         tst    al        ; Are we at the terminating '\0'?
  816.         jz    endstring
  817.         mov    cx, 1
  818.         call    [writemethod]
  819.         call    vpadjust
  820.         jmp    getnextc
  821.         even
  822. endstring:
  823.     if DPTRSIZE eq 4
  824.         pop    ds
  825.     endif
  826.         pop    si
  827.         C_ret
  828.  
  829. scrollah:
  830.         ;
  831.         ; void scroll_up(unsigned startline,
  832.         ;         unsigned endline,
  833.         ;         unsigned nlines);
  834.         ;
  835.         ; void scroll_down(unsigned startline,
  836.         ;           unsigned endline,
  837.         ;           unsigned nlines);
  838.         ;
  839.         push    bp
  840.         mov    bp, sp
  841.         mov    al, byte ptr [bp + CPTRSIZE + 6]
  842.                         ; Number of lines.
  843.         tst    al            ; If 0 lines ...
  844.         jz    noscroll        ; ... do nothing.
  845.         clear    cl            ; Top left column (0).
  846.         mov    ch, byte ptr [bp + CPTRSIZE + 2]
  847.                         ; Top left row.
  848.         mov    dl, ncolumns        ; Bottom right column.
  849.         dec    dl
  850.         mov    dh, byte ptr [bp + CPTRSIZE + 4]
  851.                         ; Bottom right row.
  852.         mov    bh, vcolour        ; Colour for blank lines.
  853.         vbios
  854. noscroll:
  855.         pop    bp
  856.         C_ret
  857.  
  858. _scroll_up:
  859.         ;
  860.         ; Scroll region of screen up.
  861.         ;
  862.         mov    ah, B_UPSCROLL
  863.         jmp    scrollah
  864.  
  865. _scroll_down:
  866.         ;
  867.         ; Scroll region of screen down.
  868.         ;
  869.         mov    ah, B_DOWNSCROLL
  870.         jmp    scrollah
  871.  
  872. _alert:
  873.         ;
  874.         ; void alert(void);
  875.         ;
  876.         call    _cparams
  877.         ;
  878.         ; cparams() gives us the current text colour in al,
  879.         ; the status line colour in ah & a visual bell flag in
  880.         ; dx; if this is non-zero, we use a visual bell
  881.         ; instead of an audible bell.
  882.         ;
  883.         push    bp
  884.         tst    dx
  885.         pushf        ; Save processor flags on stack.
  886.                 ; Zero flag means use audible bell.
  887.         jz    ab_on
  888.         ;
  889.         ; Visual bell. Set overscan colour to the background
  890.         ; component of the current text colour (or, if this is
  891.         ; black, the background component of the current
  892.         ; status line colour) temporarily.
  893.         ;
  894.         ; To get the backround component, we have to shift the
  895.         ; value right 4 bits.
  896.         ;
  897.         mov    cl, 4
  898.         shr    al, cl        ; Get text background colour.
  899.         mov    bh, al
  900.         tst    al
  901.         jnz    gotcolour    ; Text background colour isn't black.
  902.         shr    ah, cl        ; Get status line background colour.
  903.         mov    bh, ah
  904. gotcolour:
  905.         vbios    B_SETPALETTE, B_OVERSCAN
  906.         jmp short asdelay
  907. ab_on:
  908.         ;
  909.         ; Audible bell. Make speaker sound by programming the
  910.         ; timer chip & the 8255 directly.
  911.         ;
  912.         cli
  913.         mov    dx, TIMER_3
  914.         mov    al, 0b6h
  915.         out    dx, al        ; Select timer channel 2 mode.
  916.         dec    dx
  917.         ;
  918.         ; Send frequency data to timer. This gives us a
  919.         ; frequency of about 2 kHz.
  920.         ;
  921.         mov    al, 99h        ; Low byte of timer interval.
  922.         out    dx, al
  923.         mov    al, 2        ; High byte of timer interval.
  924.         out    dx, al
  925.         mov    dx, PORT_B
  926.         in    al, dx        ; Get status of port B.
  927.         mov    ah, al        ; Store it in ah.
  928.         or    al, 3
  929.         out    dx, al        ; Turn speaker on.
  930.         sti
  931.         ;
  932.         ; Delay for 3 clock ticks (about 1/9 - 1/6 sec.).
  933.         ;
  934.         ; Don't change ah or dx.
  935.         ;
  936. asdelay:
  937.         mov    cx, 3
  938.         mov    bx, BVSEG
  939.         mov    es, bx
  940.         assume    es: BIOSDATA
  941. tloop:
  942.         mov    bx, b_timer_low
  943. waittick:
  944.         cmp    bx, b_timer_low
  945.         je    waittick
  946.         loop    tloop
  947.         ;
  948.         ; Delay loop has now finished.
  949.         ;
  950.         popf            ; Retrieve flags from stack.
  951.         jz    ab_off        ; Zero flag means use audible bell.
  952.         clear    bh        ; Set border colour to black.
  953.         vbios    B_SETPALETTE, B_OVERSCAN
  954.         jmp short ab_finish
  955. ab_off:
  956.         mov    al, ah        ; Previous status of port B.
  957.         and    al, not 3
  958.         out    dx, al        ; Turn speaker off.
  959. ab_finish:
  960.         pop    bp
  961.         assume    es: nothing
  962.         C_ret
  963.  
  964. _TEXT        ends
  965.         end
  966.